#include "TextureMaterial.h"
#include "DirectX\Shader.h"
#include "DirectX\Model.h"
#include "DirectX\Texture.h"
#include "DirectX\RenderableEntity.h"
#include "DirectX\Device.h"
#include "DirectX\Camera.h"
#include "DirectX\Utility.h"

using namespace Graphics;

RTTI_DEFINITIONS(TextureMaterial)

#ifdef DX_11
#include "DirectX\TextureShader.h"

TextureMaterial::TextureMaterial(void)
	:Graphics::Material("","")
{

}

TextureMaterial::~TextureMaterial()
{
}

void TextureMaterial::Initialize()
{
	Graphics::TextureShader* shader = MY_NEW(Memory::HID_Rendering,"TextureShader") TextureShader();
	shader->Initialize();

	mShader = shader;
}

void TextureMaterial::Deinitialize()
{

}

void TextureMaterial::Update(Graphics::RenderableEntity* entity)
{
}

void TextureMaterial::Render(Graphics::RenderableEntity* entity)
{
	D3DXMATRIX worldMatrix, viewMatrix, projectionMatrix;

	// Get the world, view, and ortho matrices from the camera and d3d objects.
	D3DXMatrixIdentity(&worldMatrix);
	viewMatrix = Utility::NeroToDXD(GetPlatform()->GetCamera()->GetViewMatrix());

	Graphics::D3DDevice* device = GetPlatform()->GetDevice()->As<Graphics::D3DDevice>();
	projectionMatrix = device->GetProjectionMatrix();

	// Put the model vertex and index buffers on the graphics pipeline to prepare them for drawing.
	entity->Render();

	//Render the model with the texture shader.
	Graphics::TextureShader* shader = mShader->As<TextureShader>();
	Graphics::D3DDevice* nDevice = GetPlatform()->GetDevice()->As<Graphics::D3DDevice>();

	/*shader->Render( entity->GetModel()->GetIndexCount(),
					worldMatrix,
					viewMatrix,
					projectionMatrix,
					entity->GetModel()->GetTexture());*/
}

void TextureMaterial::BeginRender()
{
}

void TextureMaterial::EndRender()
{
}

#elif defined(DX_9)
TextureMaterial::TextureMaterial(void)
	:Material("TextureMaterial","not used"),
	 MATERIAL_PARAM_INITIALIZATION(WorldViewProjection),
	 MATERIAL_PARAM_INITIALIZATION(AmbientColor),
	 MATERIAL_PARAM_INITIALIZATION(ColorTexture)
{
}

TextureMaterial::~TextureMaterial(void)
{
}

void TextureMaterial::Initialize()
{
	Material::Initialize();
	mShader->Initialize();

	HRESULT hr;
	D3DXHANDLE parameterHandle;
	for(int i = 0; ; i++)
	{
		parameterHandle = mShader->GetEffect()->GetParameter(NULL, i);
		if(!parameterHandle)
		{
			break;
		}

		D3DXPARAMETER_DESC parameterDescription;
		hr = mShader->GetEffect()->GetParameterDesc(parameterHandle,&parameterDescription);
		CHECK(hr);

		UINT count = 0;
		switch(parameterDescription.Class)
		{
			case D3DXPC_SCALAR:
				break;
			case  D3DXPC_VECTOR:
				count = parameterDescription.Elements;
				break;
			case D3DXPC_MATRIX_ROWS:
			case D3DXPC_MATRIX_COLUMNS:
				count = parameterDescription.Columns;
				break;
			case D3DXPC_OBJECT:
				count =  1;
				break;
			case D3DXPC_STRUCT:
				break;
			default:
			//	throw RendException("Win32Material::SetParameter::Type Not Supported",__FILE__,__LINE__);
			return;
		}

		Graphics::ShaderParameter* newEffectParameter = MY_NEW(Memory::HID_Rendering, "ShaderParameter") ShaderParameter(this,parameterHandle,parameterDescription,NULL,count);
		mParameters.insert(ParameterPair(newEffectParameter->GetDescription().Name,newEffectParameter));
	}
	MATERIAL_PARAM_RETRIEVE(WorldViewProjection)
	MATERIAL_PARAM_RETRIEVE(AmbientColor)
	MATERIAL_PARAM_RETRIEVE(ColorTexture)
}

void TextureMaterial::Deinitialize()
{
}

void TextureMaterial::Update(Graphics::RenderableEntity* entity)
{
	assert(entity);
	Graphics::Model* model = entity->GetModel();
	
	this->WorldViewProjection() << &entity->WorldViewProj();
	this->AmbientColor()		<< D3DXVECTOR4(1,1,1,1);
	if(model)
	{
		this->ColorTexture()		<< model->GetTexture()->GetResource();
	}
}

void TextureMaterial::Render(Graphics::RenderableEntity* entity)
{
	BeginRender();
	entity->Render();
	EndRender();
}

void TextureMaterial::BeginRender()
{
	Graphics::D3DDevice* nDevice = GetPlatform()->GetDevice()->As<Graphics::D3DDevice>();
	nDevice->GetDevice()->SetRenderState(D3DRS_LIGHTING, TRUE); 
	nDevice->GetDevice()->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
	
	mShader->Begin();
	for(UINT j = 0; j < mShader->PassCount(); j++)
	{
		mShader->GetEffect()->BeginPass(j);
	}
}

void TextureMaterial::EndRender()
{
	for(UINT j = 0; j < mShader->PassCount(); j++)
	{
		mShader->GetEffect()->EndPass();
	}
	mShader->End();
}

MATERIAL_PARAM_DEFINITION(TextureMaterial, WorldViewProjection)
MATERIAL_PARAM_DEFINITION(TextureMaterial, AmbientColor)
MATERIAL_PARAM_DEFINITION(TextureMaterial, ColorTexture)
#endif